package com.cskaoyan.javase.object._1getclass;

/**
 * getClass方法
 * 方法的声明：public final native Class<?> getClass();
 *      首先方法的访问权限是public，所以使用起来不用担心权限问题
 *      该方法final修饰，说明该方法不能重写，但是可以继承
 *      native表示该方法是一个本地方法，依赖于Java语言以为的语言实现，没有方法体。
 *      Class<?>是返回值类型，Class是一个类，<?>是泛型，这里我们可以忽略掉它，因为Java的泛型是伪泛型，它不影响代码
 *          执行，只影响代码编译。
 *     方法名是getClass，并且这个方法不需要参数。
 *
 * 方法的作用：获取Class对象
 *      但是什么是Class对象呢？Class对象有啥用呢？为什么要获取呢？
 *      Class对象是类加载时期（加载时期），JVM自动在堆上创建的一个对象，这个对象当中会存放该类的类型信息：
 *          比如类名是什么，包在哪里，有什么方法，有什么变量，有什么构造器等等
 *      于是，在程序的运行期间，程序员只需要获取某个类的Class对象，就可以获取该类的类型信息了。
 *      正是因为Class对象的这个特点，Class对象也叫做类的运行时对象
 *          还有叫类对象的
 *
 *      Java中的反射技术，就是依赖于Class对象实现的，通过获取类型信息，并且可以破解私有权限，反射可以做到"为所欲为"
 *
 * 注意事项：
 *      1.Class对象是类加载时期，JVM创建的。不是程序员创建的，更不是getClass方法创建的。
 *          getClass只是获取引用，指向Class对象
 *
 *      2.某个类的类加载在程序的一次运行期间，至多有一次，那么相应的该类的Class对象也是唯一的！！
 *          a.同一种类的对象调用getClass方法，得到的是同一个对象
 *          b.不同类型的对象调用getClass方法，得到的一定不是同一个对象
 *          所以getClass方法可以用来判断两个引用所指向的对象是否是同类型对象！
 *
 *
 *
 * @since 09:44
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s1 = new Student(18);
        Class stuClazz1 = s1.getClass();
        Student s2 = new Student(28);
        Class stuClazz2 = s2.getClass();
        Student s3 = new Student();
        Class stuClazz3 = s3.getClass();
        // 双等号比较地址，只有是同一个对象，才会返回true
        System.out.println(stuClazz1 == stuClazz2);
        System.out.println(stuClazz2 == stuClazz3);
        System.out.println(stuClazz1 == stuClazz3);

        Teacher t = new Teacher();
        Class teacherClazz = t.getClass();
        System.out.println(teacherClazz == stuClazz1);

        /*
            // 获取类的全限定类名
                 getName()
            // 获取类名
                 getSimpleName()
         */
        String name = teacherClazz.getName();
        String simpleName = teacherClazz.getSimpleName();
        System.out.println(name);
        System.out.println(simpleName);

        System.out.println("----------------------");
        Class<? extends Student> stuClazz = s1.getClass();
        Class<? extends Teacher> teacherClass = t.getClass();
        // Operator '==' cannot be applied to 'java.lang.Class<capture<? extends com.cskaoyan.javase.object._1getclass.Student>>', 'java.lang.Class<capture<? extends com.cskaoyan.javase.object._1getclass.Teacher>>'
        /*
            这里之所以报错是因为多了一个泛型，Java的泛型在编译时期生效，所以在编译器看来：
                Class<? extends Student>
                Class<? extends Teacher>
            不是同一个引用，所以不能用"=="连接。
         */
        // System.out.println(stuClazz == teacherClass);

    }
}

class Student {
    private int age;

    public Student() {
    }

    public Student(int age) {
        this.age = age;
    }
}

class Teacher {
}
